import React, { Component } from 'react'
import {
  StyleSheet,
  Text,
  View,
  Image,
  Dimensions,
  Modal,
  TextInput,
  AlertIOS,
  TouchableOpacity,
  AsyncStorage,
  ProgressViewIOS
} from 'react-native'
import _ from 'lodash'
import Icon from 'react-native-vector-icons/Ionicons'
import Button from 'react-native-button'
import Video from 'react-native-video'
import Sound from 'react-native-sound'
import * as Progress from 'react-native-progress'
import { AudioRecorder, AudioUtils } from 'react-native-audio'
import ImagePicker from 'react-native-image-picker'
import CountDown from 'react-native-countdown-component'
import request from '../common/request'
import { api, cloudinary, qiniu } from '../common/config'

const width = Dimensions.get('window').width
const height = Dimensions.get('window').height
let sound

let defaultState = {
  previewVideo: null,
  audioId: null,
  videoId: null,
  title: '',
  modalVisible: false,
  publishing: false,
  willPublish: false,
  publishProgress: 0.01,

  // video upload
  video: null,
  videoUploaded: false,
  videoUploading: false,
  videoUploadedProgress: 0.01,

  // video loads
  videoTotal: 0,
  currentTime: 0,

  // video player
  rate: 1,
  muted: true,
  resizeMode: 'contain',
  repeat: false,

  // count down
  counting: false,
  recording: false,

  // audio
  audio: null,
  audioPath: AudioUtils.DocumentDirectoryPath + '/test.aac',
  audioPlaying: false,
  recordDone: false,
  audioUploadedProgress: 0.01
}


class Edit extends Component {
  constructor(props) {
    super(props)

    let state = _.clone(defaultState)
    state.user = this.props.user || {}

    this.state = state
  }

  componentDidMount() {
    AsyncStorage.getItem('user')
      .then(data => {
        let user
        if (data) {
          user = JSON.parse(data)
        }

        if (user && user.accessToken) {
          this.setState({
            user: user
          })
        }
      })

    this._initAudio()
  }

  _initAudio() {
    AudioRecorder.requestAuthorization()
      .then(isAuthorised => {
        if (!isAuthorised) return

        AudioRecorder.prepareRecordingAtPath(this.state.audioPath, {
          SampleRate: 22050,
          Channels: 1,
          AudioQuality: "Hign",
          AudioEncoding: "aac",
          AudioEncodingBitRate: 32000
        })
      })
  }

  _uploadAudio() {
    const timestamp = Date.now()

    this._getToken({
      type: 'audio',
      timestamp: timestamp,
      cloud: 'cloudinary'
    }).then(data => {
      if (data && data.success) {
        const signature = data.data.token
        const key = data.data.key
        const tags = 'app,audio'
        const folder = 'audio'

        let body = new FormData()
        body.append('folder', folder)
        body.append('signature', signature)
        body.append('tags', tags)
        body.append('timestamp', timestamp)
        body.append('api_key', cloudinary.api_key)
        body.append('resource_type', 'video')
        body.append('file', {
          type: 'video/mp4',
          uri: this.state.audioPath,
          name: key
        })

        this._upload(body, 'audio')
      }
    }).catch(error => {
      console.warn(error)
    })

  }

  _getToken(body) {
    body.accessToken = this.state.user.accessToken
    const signatureUrl = api.base + api.signature

    return request.post(signatureUrl, body)
  }

  _pickVideo() {
    const videoOptions = {
      title: '选择视频',
      cancelButtonTitle: '取消',
      takePhotoButtonTitle: '录制10秒视频',
      chooseFromLibraryButtonTitle: '选择已有视频',
      noData: false,
      videoQuality: 'medium',
      mediaType: 'video',
      durationLimit: 10,
      storageOptions: {
        skipBackup: true,
        path: 'images'
      },
    }

    ImagePicker.showImagePicker(videoOptions, res => {
      if (res.didCancel) return

      let state = _.clone(defaultState)

      const uri = res.uri
      state.previewVideo = uri
      state.user = this.state.user

      this.setState(state)

      this._getToken({
        type: 'video',
        cloud: 'qiniu'
      })
        .catch(error => {
          console.warn(error)
          AlertIOS.alert('上传出错！')
        })
        .then(data => {
          if (data && data.success) {
            const token = data.data.token
            const key = data.data.key

            let body = new FormData()
            body.append('token', token)
            body.append('key', key)
            body.append('file', {
              type: 'video/mp4',
              uri: uri,
              name: key
            })

            this._upload(body, 'video')
          }
        })
    })
  }

  _upload(body, type) {
    let xhr = new XMLHttpRequest()
    let url = qiniu.uploadUrl

    if (type === 'audio') {
      url = cloudinary.audio
    }

    let state = {}
    state[type + 'Uploading'] = true
    state[type + 'Uploaded'] = false
    state[type + 'loadedProgess'] = 0.01

    this.setState(state)

    xhr.open('POST', url)
    xhr.onload = () => {
      if (xhr.status !== 200) {
        AlertIOS.alert('请求失败')
        console.log(xhr.responseText)

        return
      }

      if (!xhr.responseText) {
        AlertIOS.alert('请求失败')

        return
      }

      let response

      try {
        response = JSON.parse(xhr.response)
      }
      catch (e) {
        console.log(e)
        console.log('parse fails')
      }

      if (response) {
        console.log(response)

        state = {}
        state[type] = response
        state[type + 'Uploading'] = false
        state[type + 'Uploaded'] = true
        state[type + 'loadedProgess'] = 0.01

        this.setState(state)

        // 音视频上传后把返回信息存数据库
        const updateUrl = api.base + api[type]
        const accessToken = this.state.user.accessToken
        let updateBody = {
          accessToken: accessToken
        }
        updateBody[type] = response

        if (type === 'audio') {
          updateBody.videoId = this.state.videoId
        }

        request.post(updateUrl, updateBody)
          .then(data => {
            if (data && data.success) {
              let mediaState = {}
              mediaState[type + 'Id'] = data.data

              // 音频上传成功后打开模态窗
              if (type = 'audio') {
                this._showModal()
                mediaState.willPublish = true
              }

              this.setState(mediaState)
            } else {
              if (type === 'video')
                AlertIOS.alert('视频同步出错，请重新上传！')
              else if (type === 'audio')
                AlertIOS.alert('音频同步出错，请重新上传！')
            }
          })
          .catch(error => {
            console.warn(error)
            if (type === 'video')
              AlertIOS.alert('视频同步出错，请重新上传！')
            else if (type === 'audio')
              AlertIOS.alert('音频同步出错，请重新上传！')
          })
      }
    }

    // 上传进度
    if (xhr.upload) {
      xhr.upload.onprogress = event => {
        if (event.lengthComputable) {
          let percent = Number((event.loaded / event.total).toFixed(2))

          let progressState = {}
          progressState[type + 'UploadedProgress'] = percent

          this.setState(progressState)
        }
      }
    }

    xhr.send(body)
  }


  _pop() {
    this.props.navigator.pop()
  }

  _onLoadStart() {
    console.log('load start')
  }

  _onLoad() {
    console.log('loads')
  }

  _onProgress(data) {
    let duration = data.playableDuration
    let currentTime = data.currentTime
    let percent = Number((currentTime / duration).toFixed(2))

    this.setState({
      videoTotal: duration,
      currentTime: Number(currentTime.toFixed(2)),
      videoUploadedProgress: percent
    })
  }

  _onEnd() {
    if (this.state.recording) {
      AudioRecorder.stopRecording()

      this.setState({
        videoProgess: 1,
        recordDone: true,
        recording: false
      })
    }
  }

  _onError(e) {
    this.setState({
      videoOk: false
    })
  }

  _record() {
    this.setState({
      videoProgess: 0,
      recordReady: true,
      counting: false,
      recordDone: false,
      recording: true
    })

    AudioRecorder.startRecording()
    this.refs.videoPlayer.seek(0)
  }

  _counting() {
    if (!this.state.counting && !this.state.recording && !this.state.audioPlaying) {
      this.setState({
        counting: true
      })
    }

    this.refs.videoPlayer.seek(this.state.videoTotal - 0.01)
  }

  _preview() {
    if (this.state.audioPlaying) {
      sound = null
    }

    this.setState({
      videoProgess: 0,
      audioPlaying: true
    })

    sound = new Sound(this.state.audioPath, '', error => {
      if (error) {
        console.log('读取音频出错！', error);
      }
    })

    sound.play()
    this.refs.videoPlayer.seek(0)
  }

  _closeModal() {
    this.setState({
      modalVisible: false
    })
  }

  _showModal() {
    this.setState({
      modalVisible: true
    })
  }

  _submit() {
    const body = {
      title: this.state.title,
      videoId: this.state.videoId,
      audioId: this.state.audioId
    }

    const creationUrl = api.base + api.creations
    const user = this.state.user

    if (user && user.accessToken) {
      body.accessToken = user.accessToken

      this.setState({
        publishing: true
      })

      request.post(creationUrl, body)
        .catch(error => {
          console.log(error)
          AlertIOS.alert('视频发布失败')
        })
        .then(data => {
          if (data && data.success) {
            this._closeModal()
            AlertIOS.alert('视频发布成功')

            let state = _.clone(defaultState)
            this.setState(defaultState)
          } else {
            AlertIOS.alert('视频发布失败')

            this.setState({
              publishing: true
            })
          }
        })
    }
  }

  render() {
    return (
      <View style={styles.container}>
        <View style={styles.toolbar}>
          <Text style={styles.toolbarTitle}>
            {
              this.state.previewVideo ? '点击按钮配音' : '从配音开始'
            }
          </Text>
          {
            this.state.previewVideo && this.state.videoUploaded
              ? <Text
                style={styles.toolbarExtra}
                onPress={() => { this._pickVideo() }}>更换视频</Text>
              : null
          }
        </View>

        <View style={styles.page}>
          {
            this.state.previewVideo
              ? <View style={styles.videoContainer}>
                <View style={styles.videoBox}>
                  <Video
                    ref='videoPlayer'
                    source={{ uri: this.state.previewVideo }}
                    style={styles.video}
                    volume={5}
                    paused={this.state.paused}
                    rate={this.state.rate}
                    muted={this.state.muted}
                    resizeMode={this.state.resizeMode}
                    repeat={this.state.repeat}

                    onLoadStart={this._onLoadStart.bind(this)}
                    onLoad={this._onLoad.bind(this)}
                    onProgress={this._onProgress.bind(this)}
                    onEnd={this._onEnd.bind(this)}
                    onError={this._onError.bind(this)} />
                  {
                    !this.videoUploaded && this.state.videoUploading
                      ? <View style={styles.progressTipBox}>
                        <ProgressViewIOS
                          style={styles.progressBar}
                          progressTintColor="#ee753c"
                          progress={this.state.videoUploadedProgress} />
                        <Text style={styles.progressTip}>
                          正在生成静音视频，已完成
                        {(this.state.videoUploadedProgress * 100).toFixed(2)}%
                      </Text>
                      </View>
                      : null
                  }

                  {
                    this.state.recording || this.state.audioPlaying
                      ? <View style={styles.progressTipBox}>
                        <ProgressViewIOS
                          style={styles.progressBar}
                          progressTintColor="#ee753c"
                          progress={this.state.videoProgess} />
                        {
                          this.state.recording
                            ? <Text style={styles.progressTip}>录制声音中...</Text>
                            : null
                        }
                      </View>
                      : null
                  }

                  {
                    this.state.recordDone
                      ? <View style={styles.previewBox}>
                        <Icon
                          name='ios-play'
                          style={styles.previewIcon} />
                        <Text
                          style={styles.previewText}
                          onPress={this._preview.bind(this)}
                        >预览</Text>
                      </View>
                      : null
                  }

                </View>
              </View>
              : <TouchableOpacity
                style={styles.uploadContainer}
                onPress={() => { this._pickVideo() }}>
                <View style={styles.uploadBox}>
                  <Image
                    source={require('../assets/images/record.png')}
                    style={styles.uploadIcon} />
                  <Text style={styles.uploadTitle}>点击上传视频</Text>
                  <Text style={styles.uploadNotice}> 建议视频时长不超过20秒</Text>
                </View>
              </TouchableOpacity>
          }

          {
            this.state.videoUploaded
              ? <View style={styles.recordBox}>
                <View
                  style={[styles.recordIconBox, (this.state.recording || this.state.audioPlaying) && styles.recordOn]}>
                  {
                    this.state.counting && !this.state.recording
                      ? <View style={styles.countDownBox}>
                        {
                          this.state.counting
                            ? <CountDown
                              style={styles.CountDownBtn}
                              digitStyle={{ backgroundColor: 'transparent' }}
                              digitTxtStyle={{ color: '#fff' }}
                              until={3}
                              onFinish={() => this._record()}
                              timeToShow={['S']}
                              timeLabels={{ s: null }}
                              size={30} />
                            : <Text style={styles.timeLabel}>Go</Text>
                        }
                      </View>
                      : <TouchableOpacity onPress={() => { this._counting() }}>
                        <Icon
                          name='ios-mic'
                          style={styles.recordIcon} />
                      </TouchableOpacity>
                  }

                </View>
              </View>
              : null
          }

          {
            this.state.videoUploaded && this.state.recordDone
              ? <View style={styles.uploadAudioBox}>
                {
                  !this.state.audioUploaded && !this.state.audioUploading
                    ? <Text style={styles.uploadAudioText} onPress={this._uploadAudio.bind(this)}>下一步</Text>
                    : null
                }

                {
                  this.state.audioUploading
                    ? <Progress.Circle
                      size={60}
                      showsText={true}
                      color={'#ee753c'}
                      progress={this.state.audioUploadedProgress} />
                    : null
                }
              </View>
              : null
          }

        </View>

        <Modal
          visible={this.state.modalVisible}>
          <View style={styles.modalContainer}>
            <Icon
              onPress={() => this._closeModal()}
              name='ios-close'
              style={styles.closeIcon} />

            {
              this.state.audioUploaded && !this.state.publishing
                ? <View style={styles.fieldBox}>
                  <TextInput
                    placeholder='输入视频标题'
                    style={styles.inputField}
                    autoCapitalize={'none'}
                    autoCorrect={false}
                    defaultValue={this.state.title}
                    onChangeText={text => {
                      this.setState({
                        title: text
                      })
                    }}
                  />
                </View>
                : null
            }

            {
              this.state.publishing
                ? <View style={styles.loadingBox}>
                  <Text style={styles.loadingText}>玩命生成视频中...</Text>
                  {
                    this.state.willPublish
                      ? <Text style={styles.loadingText}>合并视频和音频...</Text>
                      : null
                  }

                  {
                    this.state.publishProgress > 0.3
                      ? <Text style={styles.loadingText}>开始上传...</Text>
                      : null
                  }

                  <Progress.Circle
                    size={60}
                    showsText={true}
                    color={'#ee753c'}
                    progress={this.state.publishProgress} />
                </View>
                : null
            }



            <View style={styles.submitBox}>
              {
                this.state.audioUploaded && !this.state.publishing
                  ? <Button style={styles.submitBtn} onPress={() => { this._submit() }}>发布视频</Button>
                  : null
              }
            </View>
          </View>
        </Modal>


      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1
  },

  toolbar: {
    flexDirection: 'row',
    paddingTop: 25,
    paddingBottom: 12,
    backgroundColor: '#ee753c'
  },

  toolbarTitle: {
    flex: 1,
    fontSize: 16,
    color: '#fff',
    textAlign: 'center',
    fontWeight: '600'
  },

  toolbarExtra: {
    position: 'absolute',
    right: 10,
    top: 26,
    color: '#fff',
    textAlign: 'right',
    fontWeight: '600',
    fontSize: 14
  },

  page: {
    flex: 1,
    alignItems: 'center'
  },

  uploadBox: {
    justifyContent: 'center',
    alignItems: 'center'
  },

  uploadContainer: {
    marginTop: 90,
    width: width - 40,
    paddingBottom: 10,
    borderWidth: 1,
    borderColor: '#ee753c',
    justifyContent: 'center',
    borderRadius: 6,
    backgroundColor: '#fff'
  },

  uploadTitle: {
    textAlign: 'center',
    marginBottom: 10,
    fontSize: 16,
    color: '#000'
  },

  uploadNotice: {
    color: '#999',
    textAlign: 'center',
    fontSize: 12
  },

  uploadIcon: {
    width: 150,
    resizeMode: 'contain'
  },

  videoContainer: {
    width: width,
    justifyContent: 'center',
    alignItems: 'flex-start'
  },

  videoBox: {
    width: width,
    height: height * 0.6
  },

  video: {
    width: width,
    height: height * 0.6,
    backgroundColor: '#333'
  },

  progressTipBox: {
    position: 'absolute',
    left: 0,
    bottom: 0,
    width: width,
    height: 30,
    backgroundColor: 'rgba(244,244,244,.65)'
  },

  progressTip: {
    color: '#333',
    width: width - 10,
    padding: 5
  },

  progressBar: {
    width: width
  },

  recordBox: {
    width: width,
    height: 60,
    alignItems: 'center'
  },

  recordIconBox: {
    width: 68,
    height: 68,
    marginTop: -30,
    borderRadius: 34,
    backgroundColor: '#ee753c',
    borderWidth: 1,
    borderColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center'
  },

  recordOn: {
    backgroundColor: '#ccc'
  },

  recordIcon: {
    fontSize: 58,
    color: '#fff'
  },

  countDownBox: {
    width: 68,
    height: 68,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#ee753c',
    borderRadius: 34
  },

  CountDownBtn: {
    height: 40,
    flexDirection: 'row',
  },

  timeLabel: {
    color: '#fff',
    fontSize: 30,
    paddingRight: 10
  },

  previewBox: {
    width: 80,
    height: 30,
    position: 'absolute',
    right: 10,
    bottom: 10,
    borderWidth: 1,
    borderColor: '#ee753c',
    borderRadius: 3,
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center'
  },

  previewIcon: {
    marginRight: 5,
    fontSize: 20,
    color: '#ee753c',
    backgroundColor: 'transparent'
  },

  previewText: {
    fontSize: 20,
    color: '#ee753c',
    backgroundColor: 'transparent'
  },

  uploadAudioBox: {
    width: width,
    height: 60,
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center'
  },

  uploadAudioText: {
    width: width - 20,
    padding: 5,
    borderWidth: 1,
    borderColor: '#ee753c',
    borderRadius: 5,
    textAlign: 'center',
    fontSize: 30,
    color: '#fff',
    backgroundColor: '#ee753c'
  },

  modalContainer: {
    width: width,
    height: height,
    paddingTop: 50,
    backgroundColor: '#fff'
  },

  closeIcon: {
    position: 'absolute',
    fontSize: 32,
    right: 10,
    top: 30,
    color: '#ee753c'
  },

  fieldBox: {
    width: width - 40,
    height: 36,
    marginTop: 30,
    marginLeft: 20,
    marginRight: 20,
    borderBottomWidth: 1,
    borderBottomColor: '#eee'
  },

  inputField: {
    height: 36,
    textAlign: 'center',
    color: '#666',
    fontSize: 14
  },

  loadingBox: {
    width: width,
    height: 50,
    marginTop: 10,
    padding: 15,
    alignItems: 'center'
  },

  loadingText: {
    marginBottom: 10,
    textAlign: 'center',
    color: '#333'
  },

  submitBox: {
    marginTop: 50,
    padding: 15
  },

  submitBtn: {
    width: width - 50,
    padding: 16,
    marginLeft: 10,
    marginRight: 10,
    marginTop: 90,
    marginBottom: 20,
    borderWidth: 1,
    borderColor: '#ee753c',
    backgroundColor: '#ee753c',
    borderRadius: 4,
    color: '#fff',
    fontSize: 18
  }

})

module.exports = Edit